home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-04-04 | 16.5 KB | 539 lines | [TEXT/KAHL] |
- /***************************************************** IMPLEMENTATION
- DATE: 9/26/93
- AUTHOR: Eric R. Rosé
-
- CLASS: CPPSendWindow
-
- SUPERCLASS: CPPWindow
-
- This C++ class manages the NetApp Send window
-
- ********************************************************************/
-
- #include "CPPSendWindow.h"
- #include "CPPMessageWindow.h"
- #include <CPPPictButton.h>
- #include <CPPButton.h>
- #include <CPPCheckBox.h>
- #include <CPPStaticText.h>
- #include "CPPZoneList.h"
- #include "CPPUserList.h"
- #include "CPPVisualList.h"
- #include "CPPWatchWriteTask.h"
- #include <CPPText.h>
- #include <CPPConnectTask.h>
- #include <CPPSound.h>
- #include <CPPMaBell.h>
- #include <CPPWriteTask.h>
- #include <CPPNode411.h>
- #include <CPPStringList.h>
- #include <CPPZone411.h>
- #include <CPPNodeInfo.h>
- #include <CPPVisualObjectList.h>
- #include <CPPDRequest.h>
- #include <stdio.h>
- #include <string.h>
- #include <script.h>
- #include "MyGlobals.h"
- #include <ConvertTools.h>
- #include <StringTools.h>
- #include <ToolboxTools.h>
- #include <MemoryTools.h>
-
- #define SendWindowID 200
- #define kSendButton -1
- #define kZoneButton -2
- #define kUserListClick -3
- #define kZoneListClick -4
-
- extern StringPtr gReplyString;
- extern RGBColor RGBRed;
- extern CPPZoneList *gZoneList; // pointer to the send dialog's zone list
- extern CPPUserList *gUserList; // pointer to the send dialog's user list
- extern CPPMaBell *gMaBell;
- extern CPPTaskManager *gSlaveDriver;
- extern CPPNodeInfo *gOurIdentity;
- extern CPPList *gTalkText;
- extern PPCPortRefNum gOurPort;
- extern PrefsData gPrefsInfo;
- extern CPPSendWindow *gSendWindow;
- extern CPPMessageWindow *gMessageWindow;
- extern CPPSound *gIncomingSound;
- extern CPPSound *gLogonSound;
- extern StringPtr gAppName;
-
- /*-----------------------------------------------------------------*/
-
- void ProcessNodeLookupResults (CPPObject *TheTask);
- void ProcessZoneLookupResults (CPPObject *TheTask);
-
- /*-----------------------------------------------------------------*/
-
- void ProcessZoneLookupResults (CPPObject *TheTask)
- /* called whenever our zone lookup task completes, this routine */
- /* simply displays the number of zones found; since the visual */
- /* ZoneList depends directly on the lookup task's data list, */
- /* all visual updating will have already taken place */
- {
- CPPZone411 *LookupTask = (CPPZone411 *)TheTask;
- long numItems = 0;
- Boolean BTemp;
- char NewMessage[255];
-
- if (LookupTask)
- numItems = LookupTask->NumZonesFound(&BTemp);
-
- sprintf (NewMessage, "Found %d zone%c.", numItems,
- (numItems == 1) ? ' ' : 's');
- gSendWindow->SetStatusMessage(Data2PString(NewMessage,
- strlen(NewMessage)), FALSE);
-
- }
- /*-----------------------------------------------------------------*/
-
- void ProcessNodeLookupResults (CPPObject *TheTask)
- /* called whenever a node lookup task completes, this routine */
- /* adds each user in turn to the user list; */
- /* NOTE: Only the unique users will actually be added - */
- /* see CPPUserList::AddNewUser */
- {
- CPPNode411 *LookupTask = (CPPNode411 *)TheTask;
- Boolean BTemp, UA = FALSE;
- long before, numUnique;
- char NewMessage[255];
-
- before = gSendWindow->UserList->GetNumItems();
-
- for (long i = 1; i <= LookupTask->NumNodesFound(&BTemp); i++)
- UA = gUserList->AddNewUser(LookupTask->NthNode (i, FALSE)) || UA;
- if (UA)
- if (gPrefsInfo.playLogon)
- gLogonSound->PlaySound(TRUE);
-
- numUnique = gSendWindow->UserList->GetNumItems() - before;
- if (numUnique)
- sprintf (NewMessage, "Found %d new user%c.", numUnique,
- (numUnique == 1) ? ' ' : 's');
- else
- sprintf (NewMessage, "No new users were found.");
- gSendWindow->SetStatusMessage(Data2PString (NewMessage, strlen(NewMessage)), FALSE);
- }
-
- /*-----------------------------------------------------------------*/
- /*------------------------ PUBLIC METHODS -------------------------*/
- /*-----------------------------------------------------------------*/
-
- CPPSendWindow::CPPSendWindow (CPPWindowManager *theManager) :
- CPPWindow (theManager, SendWindowID)
- {
- StringPtr TempString, STemp;
- Rect tempRect;
- Point tempPt;
- CPPStaticText *ST = NULL;
-
- // create the list where we will store all the users we know about
- this->UserListData = new CPPObjectList();
-
- // create the lookup tasks
- NodeLookup = new CPPNode411 (gSlaveDriver, 25, FALSE);
- ZoneLookup = new CPPZone411 (gSlaveDriver, gMaBell, 60, FALSE);
-
- // place all of the static text items
- SetRect (&tempRect, 32, 14, 136, 30);
- ST = new CPPStaticText ((CPPWindow *)this, &tempRect, 129);
-
- SetRect (&tempRect, 222, 14, 346, 30);
- ST = new CPPStaticText ((CPPWindow *)this, &tempRect, 130);
-
- SetRect (&tempRect, 14, 153, 118, 250);
- ST = new CPPStaticText ((CPPWindow *)this, &tempRect, 131);
-
- SetRect (&tempRect, 14, 288, 382, 302);
- Status = new CPPStaticText ((CPPWindow *)this, &tempRect,
- 133, geneva, 9, teJustLeft, italic, &RGBRed);
-
- // place the zone and user lists
- SetRect(&tempRect, 14, 35, 136, 148);
- ZoneList = new CPPZoneList ((CPPWindow *)this, &tempRect,
- (CPPDArray *)(ZoneLookup->GetFoundList()),
- FALSE);
- ZoneList->SetCommand (kZoneListClick);
- gZoneList = ZoneList;
-
- SetRect (&tempRect, 222, 35, 382, 148);
- UserList = new CPPUserList ((CPPWindow *)this, &tempRect,
- this->UserListData, TRUE);
- UserList->SetCommand (kUserListClick);
- gUserList = UserList;
-
- // place the textedit area
- SetRect (&tempRect, 14, 170, 382, 244);
- SendText = new CPPText ((CPPWindow *)this, &tempRect,
- &tempRect, 32000, FALSE, TRUE);
- ARWarning = new CPPStaticText((CPPWindow *)this, &tempRect,
- "\pAUTOREPLY ON:", geneva,
- 9, teJustCenter, bold, &RGBRed,
- FALSE, TRUE, FALSE);
-
- // place the 'echo' checkbox
- SetRect (&tempRect, 14, 262, 204, 278);
- CBEcho = new CPPCheckBox ((CPPWindow *)this, 128, TRUE);
-
- // place the 'load zones' picture button
- tempPt.h = 14; tempPt.v = 14;
- PBLoadZones = new CPPPictButton((CPPWindow *)this, 128, tempPt,
- kUseDarken);
- PBLoadZones->SetCommand (kZoneButton);
-
- // place the default 'send' button
- SetRect (&tempRect, 282, 260, 381, 280);
- SendButton = new CPPButton((CPPWindow *)this, 132, TRUE);
- SendButton->SetCommand (kSendButton);
-
- MakeTarget (SendText);
-
- // start by loading a list of zones
- ZoneLookup->StartZoneLookup(ProcessZoneLookupResults);
- }
-
- /*-----------------------------------------------------------------*/
-
- CPPSendWindow::~CPPSendWindow (void)
- {
- // let the standard dispose routine get rid of the window items
- }
-
- /*-----------------------------------------------------------------*/
-
- char *CPPSendWindow::ClassName (void)
- {
- return "CPPSendWindow";
- }
-
- /*-----------------------------------------------------------------*/
-
- Boolean CPPSendWindow::DoCommand (short commandID)
- /* handle commands specific to our window */
- {
- Boolean result = TRUE;
- StringPtr ZoneName;
- Str255 newMessage;
- Str32 TypeStr;
- long whichCell;
-
- switch (commandID) {
-
- case kUserListClick : // send text to selected users
- case kSendButton : // send text to selected users
- DoSendButton();
- break;
-
- case kZoneButton : // re-load the list of zones
- ZoneLookup->StartZoneLookup(ProcessZoneLookupResults);
-
- // let the user know we are scanning
- SetStatusMessage(String2String ("\pScanning network for available zones"), FALSE);
- break;
-
- case kZoneListClick : // scan zone for new users
- if (ZoneList->FirstSelectedCell (&whichCell))
- {
- ZoneName = (*this->ZoneList)[whichCell];
- if (ZoneName)
- {
- PStrCat (32, TypeStr, 2, "\pť", gAppName);
- this->NodeLookup->StartNodeLookup
- ("\p=", TypeStr, ZoneName, 50,
- ProcessNodeLookupResults);
- }
-
- // let the user know we are scanning
- PStrCat (255, newMessage, 3, "\pScanning zone '", ZoneName,
- "\p' for other Yentot.");
- SetStatusMessage(newMessage, TRUE);
- }
- break;
-
- default:
- result = CPPWindow::DoCommand(commandID);
- break;
- }
-
- return result;
- }
-
-
- /*-----------------------------------------------------------------*/
-
- void CPPSendWindow::SetStatusMessage (StringPtr newMessage, Boolean makeCopy)
- {
- if (newMessage)
- this->Status->SetitsString(newMessage, makeCopy);
- }
-
- /*-----------------------------------------------------------------*/
- /*--------------------- PROTECTED METHODS -------------------------*/
- /*-----------------------------------------------------------------*/
-
- Boolean CPPSendWindow::DoUserKey (EventRecord *theEvent)
- {
- char theKey;
- CPPList *TempList;
- StringPtr STemp;
- char s[25];
-
-
- theKey = theEvent->message & charCodeMask;
- if (!(theEvent->modifiers & cmdKey))
- {
- switch (theKey) {
- case kTab :
- if (ShiftKeyDown(theEvent->modifiers))
- {MakePreviousTarget(); return TRUE;}
- else
- {MakeNextTarget(); return TRUE;}
- break;
-
- case kEnter :
- if (SendButton)
- SendButton->SimulateClick();
- break;
- default:
- return CPPWindow::DoUserKey (theEvent);
- break;
- }
- }
- }
-
- /*-----------------------------------------------------------------*/
-
- void CPPSendWindow::RefreshItemStates()
- /* this routine is called whenever an event occurs so that */
- /* the window can check to see if any of the objects in it */
- /* should be enabled/disabled, etc. For example, if a button */
- /* should only be active when certain conditions are true, */
- /* you could use this routine to activate/deactivate it */
- {
- Str255 STemp;
- GrafPtr SavePort;
- long whichCell;
-
- GetPort (&SavePort);
- SetPort (this->theWindow);
-
- // update the text/autoreply message
- if (gReplyString)
- {
- if (SendText->IsVisible())
- {
- if (GetTarget() == SendText)
- this->MakeNextTarget();
- SendText->MakeVisible(FALSE);
- PStrCat (255, STemp, 2, "\pAUTOREPLY ON:\r", gReplyString);
- ARWarning->SetitsString(STemp, TRUE);
- ARWarning->MakeVisible(TRUE);
- }
- }
- else
- if (!SendText->IsVisible())
- {
- ARWarning->MakeVisible(FALSE);
- SendText->MakeVisible(TRUE);
- this->MakeTarget(SendText);
- }
-
- // update the enabled/disabled state of the 'Send' button
- if (UserList->FirstSelectedCell(&whichCell) && (SendText->GetTextLen()))
- {
- if (!SendButton->IsEnabled())
- SendButton->EnableButton(TRUE);
- }
- else
- {
- if (SendButton->IsEnabled())
- SendButton->EnableButton(FALSE);
- }
-
- SetPort (SavePort);
- }
-
- /*-----------------------------------------------------------------*/
-
- void CPPSendWindow::DoSendButton(void)
- /* handle the pressing of the 'send' button by sending a message */
- /* containing our address and the text in the 'send text' area */
- /* to each of the hilighted users */
- {
- long NumToSendTo = this->UserList->NumSelectedCells();
- Ptr OurIDStream = gOurIdentity->InfoToStream();
- Handle Text2Send = this->SendText->GetTheText();
- long TextLen = this->SendText->GetTextLen();
- Ptr TempPtr = NULL;
- long whichUser = 0;
- Str32 theTime;
- Str255 newMessage;
- OSErr ErrCode;
- CPPNodeInfo *UserData = NULL;
- CPPWatchWriteTasks *WatchTask;
- CPPConnectTask *CTask;
-
- // exit if there is only 1 user or no text to send
- if (!(TextLen && NumToSendTo))
- return;
-
- /* create a ptr large enough to hold our ID and the text */
- TempPtr = NewPtr(TextLen + GetPtrSize(OurIDStream));
- if ((ErrCode = MemError()) != noErr)
- ErrorAlert(ErrCode, "\pCan't send message.");
- else
- {
- BlockMove (OurIDStream, TempPtr, GetPtrSize(OurIDStream));
- BlockMove (*Text2Send, TempPtr+GetPtrSize(OurIDStream), TextLen);
- DisposPtr (OurIDStream);
-
- // if 'echo to message window' is checked, add a copy of
- // the text to our incoming message queue
- if (CBEcho->GetValue())
- gTalkText->AppendItem (Ptr2Ptr(TempPtr));
-
- // send text to each hilighted user
- while (this->UserList->NextSelectedCell(&whichUser))
- {
- UserData = (CPPNodeInfo *)((*this->UserList)[whichUser]);
- if (UserData && !(UserData->Equals(gOurIdentity)))
- SendToUser (TempPtr, NumToSendTo == 1, UserData);
- }
-
- // if there is more than one user to write to, we have to spawn
- // a task to wait for the write tasks to complete and then
- // dispose of 'TempPtr'
- if (NumToSendTo != 1)
- {
- WatchTask = new CPPWatchWriteTasks (gSlaveDriver, 60);
- WatchTask->StartWatchTask(TempPtr);
- }
-
- // display a message so they know the data was sent
- CurrentTimeString (TRUE, theTime, 32);
- PStrCat (255, newMessage, 2, "\pMessage(s) sent at ",theTime);
- SetStatusMessage(newMessage, TRUE);
- }
-
- }
-
- /*-----------------------------------------------------------------*/
-
- void CPPSendWindow::SendToUser(Ptr Text, Boolean ownsData, CPPNodeInfo *SendTo)
- /* send the passed in Text to the specified user; if ownsData is TRUE, */
- /* let the write task dispose of the data */
- {
- CPPWriteTask *TheTask;
-
- // Create a write task and have it open the connection and
- // send the data to the other user
- TheTask = new CPPWriteTask (gSlaveDriver, 25, TRUE);
- TheTask->StartWriteTask (gOurPort, SendTo, Text, ownsData, NULL,
- (OSType)'TEXT', (OSType)'YntA');
- }
-
- /*-----------------------------------------------------------------*/
-
- void CPPSendWindow::ProcessMessageQ (void)
- /* if there are any entries in gTalkText, extract the */
- /* first one and put its data in the message window */
- {
- Ptr MessageText, MessageStart;
- long MessageLen;
- Str255 Header;
- Str63 TimeString, IDString;
- long i = 1;
- CPPNodeInfo *SendersAddress;
- StringPtr ObjStr, TypeStr, ZoneStr;
- short OldTypeStrLen;
-
- // exit if there are no items in the list
- if (gTalkText->GetNumItems() == 0)
- return;
-
- // get the first item in the list; exit if empty
- MessageText = (*gTalkText)[1];
- if (!MessageText) return;
- MessageLen = GetPtrSize(MessageText);
-
- // Construct a header for the message which tells who sent it and when
- // it arrived:
- // 1. Get the user's name and address out of the message
- SendersAddress = (CPPNodeInfo *)StreamToInfo (MessageText, &MessageStart);
- // 2. Build a string in the format UserName@ZoneName
- SendersAddress->GetNodeName(&ObjStr, &TypeStr, &ZoneStr);
- while (((TypeStr[i] & 0x00FF) != 0xA5) && (i <= MessageLen))
- i++;
- OldTypeStrLen = TypeStr[0];
- TypeStr[0] = i-1;
- // 3. Get a string which specifies the arrival time
- CurrentTimeString (TRUE, TimeString, 32);
- // 4. Construct the header
- PStrCat (255, Header, 7, "\p\r<Message received from ", TypeStr,
- "\p@", ZoneStr, "\p at ", TimeString, "\p>\r•");
- TypeStr[0] = OldTypeStrLen;
-
- // 1. Insert the header
- gMessageWindow->InsertTextPtr ((Ptr)&Header[1], *Header, 32767, TRUE);
- // 2. insert the text of the message
- gMessageWindow->InsertTextPtr(MessageStart, MessageLen -
- (long)(MessageStart - MessageText),
- 32767, FALSE);
-
- if (gPrefsInfo.playMessage && !(SendersAddress->Equals(gOurIdentity)))
- gIncomingSound->PlaySound(TRUE);
-
- // now, call a method to handle the autoreply and place the
- // user's name in the list of known users.
- if (!(SendersAddress->Equals(gOurIdentity)))
- GotNewMessage (SendersAddress);
-
- DisposPtr(MessageText);
-
- gTalkText->DeleteItem(1, TRUE);
- }
-
- /*-----------------------------------------------------------------*/
-
- void CPPSendWindow::GotNewMessage (CPPNodeInfo *FromWhom)
- // check to see whether the person we received the message from
- // is in the user list. If not, search the network for him
- {
- Ptr TempPtr, OurIDStream;
- OSErr ErrCode;
-
- // check to see if 'autoreply' is on; if so, send him
- // a message in response
- if (gReplyString)
- {
- // Create a string which has our name and address in it, so that
- // the other user can add us to his list if he doesn't know about us
- OurIDStream = gOurIdentity->InfoToStream();
-
- // create a pointer big enough to hold our address, plus the data in
- // the reply string
- TempPtr = NewPtr (GetPtrSize(OurIDStream) + gReplyString[0]);
- if ((ErrCode = MemError()) == noErr)
- {
- BlockMove (OurIDStream, TempPtr, GetPtrSize(OurIDStream));
- BlockMove (gReplyString+1, TempPtr+GetPtrSize(OurIDStream), *gReplyString);
- DisposPtr (OurIDStream);
-
- // send the autoreply to the user who sent us the message
- SendToUser (TempPtr, TRUE, FromWhom);
- }
- }
-
- // Add the user to the list; if they are already in the list, nothing
- // will happen
- if (this->UserList->AddNewUser(FromWhom))
- if (gPrefsInfo.playLogon)
- gLogonSound->PlaySound(TRUE);
- }
-
- /*-----------------------------------------------------------------*/
-